﻿using ERP.Common.Util.Interfaces;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using UERP.Common.Util.Model;

namespace ERP.Common.Util.Service;

public class BaseService<T, DatabaseContext> : IBaseService<T> 
    where T : class
    where DatabaseContext : DbContext
{
    protected readonly IServiceScopeFactory _serviceScopeFactory;

    public BaseService(IServiceScopeFactory serviceScopeFactory)
    {
        _serviceScopeFactory = serviceScopeFactory;
    }

    public virtual async Task<T> CreateAsync(T entity)
    {
        using (var scope = _serviceScopeFactory.CreateScope())
        {
            using (var context = scope.ServiceProvider.GetRequiredService<DatabaseContext>())
            {
                await context.Set<T>().AddAsync(entity);
                await context.SaveChangesAsync();
                return entity;
            }
        }
    }

    public virtual async Task<T> GetByIdAsync(long id)
    {
        using (var scope = _serviceScopeFactory.CreateScope())
        {
            using (var context = scope.ServiceProvider.GetRequiredService<DatabaseContext>())
            {
                return await context.Set<T>().FindAsync(id);
            }
        }
    }

    public virtual async Task<PagedList<T>> GetAllAsync(int page = 1, int pageSize = 10)
    {
        using (var scope = _serviceScopeFactory.CreateScope())
        {
            using (var context = scope.ServiceProvider.GetRequiredService<DatabaseContext>())
            {
                PagedList<T> paged = new PagedList<T>();
                paged.Data = await context
                    .Set<T>()
                    .Skip((page - 1) * pageSize)
                    .Take(pageSize)
                    .ToListAsync();
                paged.Total = await context.Set<T>().CountAsync();

                return paged;
            }
        }
    }

    public virtual async Task<T> UpdateAsync(T entity)
    {
        using (var scope = _serviceScopeFactory.CreateScope())
        {
            using (var context = scope.ServiceProvider.GetRequiredService<DatabaseContext>())
            {
                context.Set<T>().Update(entity);
                await context.SaveChangesAsync();
                return entity;
            }
        }
    }

    public virtual async Task DeleteAsync(long id)
    {
        using (var scope = _serviceScopeFactory.CreateScope())
        {
            using (var context = scope.ServiceProvider.GetRequiredService<DatabaseContext>())
            {
                var entity = await GetByIdAsync(id);
                if (entity != null)
                {
                    context.Set<T>().Remove(entity);
                    await context.SaveChangesAsync();
                }
            }
        }
    }
}
